/**
 * Copyright (C) 2009-2010,  Magus Tech. Co., Ltd.
 * \file: op_list.h
 * \author: coanor
 * \date: 2010/4/15
 * \brief: list definition and function declarations
 ******************************************************************************/
#ifndef	OP_LIST_H
#define	OP_LIST_H
#include "c.h"
#include "nodes/nodes.h"
/**
 * list_t
 */
typedef struct list_t {
    node_tag_t      type;
    void            *elem;
    struct list_t   *next;
} list_t;

/**
 * parse_value_t
 */
typedef struct parse_value_t {
    node_tag_t      type;

    union val{
        char    *str;
        long    ival;
        double  dval;
    } val;
} parse_value_t;

#define	int_val(v)	(((value_t *)v)->val.ival)
#define	float_val(v)	(((value_t *)v)->val.dval)
#define str_val(v)	(((value_t *)v)->val.str)

#define NIL ((list_t *)NULL)

/**
 *	accessor macros
 */
#define lfirst(l)				((l)->elem)
#define lnext(l)				((l)->next)
#define lsecond(l)				(lfirst(lnext(l)))

/**
 * foreach -
 *    a convenience macro which loops through the list
 */
#define for_each(_elt_, _list_) \
    for (_elt_ = _list_; _elt_ != NIL; _elt_ = lnext(_elt_))

/*
 * function prototypes in nodes/list.c
 */
int length(list_t *list);
list_t *append(list_t *list1, list_t *list2);
list_t *nconc(list_t *list1, list_t *list2);
list_t *lcons(void *datum, list_t *list);
parse_value_t *make_integer(long i);
parse_value_t *make_float(double d);
parse_value_t *make_string(char *str);
list_t *make_list(void *elem, ...);
list_t *lappend(list_t *list, void *obj);
list_t *lremove(void *elem, list_t *list);
void free_list(list_t *list);

void *nth(int n, list_t *l);
void set_nth(list_t *l, int n, void *elem);

#define	lconsi(i,l)	lcons((void*)(int)i,l)
#define lfirsti(l)	((int)lfirst(l))
#define	lappendi(l,i)	lappend(l,(void*)i)

list_t *int_append(list_t *list1, list_t *list2);

list_t *nreverse(list_t *);
list_t *set_difference(list_t *, list_t *);
list_t *set_differencei(list_t *, list_t *);
list_t *list_remove(void *, list_t *);
list_t *int_lisp_remove(int, list_t *);
list_t *list_union(list_t *foo, list_t *bar);


/* in copyfuncs.c */
list_t *list_copy(list_t *);

#endif
